Session Archive — put a session away, get it back in one step Archive is daemon truth: archive on the phone, the row is gone on the desktop too. It is not delete, not expiry, not “done”. The row leaves the regular list immediately; opening an archived session does not bring it back.
Two rules carry the whole design: put-away is a menu verb, take-back is a visible control. Archiving is deliberate, so it lives behind long-press / right-click. Unarchiving happens in a room you had to walk into on purpose, so it is a persistent trailing control on every row — never a hidden gesture.
Colour law unchanged: terracotta only on the take-back action and the active scope · green 70% = still running · muted mono for paths, counts, branches.
Frame 1 · Long-press sheet — full390×844 · entry point ⌸ in the top bar · project has groups
9:41
Sessions
Active
Fix relay reconnect
The socket drops after the phone sleeps — retrying with backoff.
running·34·fix/relay·now
Coverage report in CI
Wiring codecov into the PR check so the delta shows up.
12·ci/coverage·2h
Auth refactor
Token rotation spike
Rotating refresh tokens without logging anyone out.
58·spike/rotate·5d
Token rotation spike
~/code/cc-pocket · 58 msgs · 5d
Move to group
Active
Auth refactorcurrent
New group…
Session
Rename
Archivehides on all devices
Cancel
Sheet order is frequency, then weight: grouping is the everyday verb and sits on top; Archive is last, under a hairline-separated SESSION label, with a one-line consequence caption — hides on all devices. It is not destructive-red: archiving is reversible, and red is reserved for deny / delete.
Frame 2 · Long-press sheet — degraded390×844 · project has no groups yet · one row only
9:41
Sessions
~/code/parser
Port tokenizer to Rust
Same output as the Go version on the fixture corpus.
21·rust/tok·1d
Bench harness
Criterion setup so the port has numbers to beat.
7·main·3d
Port tokenizer to Rust
~/code/parser · 21 msgs · 1d
Rename
Archivehides on all devices
No groups in this project — create one
Cancel
Degradation rule: when a project has no groups, the MOVE TO GROUP section and its label disappear — a section header over an empty list is worse than no header. The SESSION label goes too (a label needs a sibling to distinguish from), so the sheet is a flat two-row list. The session title is doing the heading work in both states, so nothing moves when groups appear later — the sheet only grows upward. The empty-group prompt is a dashed hint at the bottom, not a row: it is a way in, not a verb on this session.
Frame 3 · Archive — mobile390×844 · cross-project, grouped by path · trailing unarchive
9:41
Archived14
~/code/cc-pocket6
Push notification spike
APNs relay worked end-to-end; parked until the daemon lands.
41·spike/apns·12d
Migrate settings store
Moved prefs off UserDefaults; merged in #418.
running·96·chore/prefs·3w
Onboarding copy pass
Rewrote the pairing screens; shipped in 1.4.
18·copy/onboard·3w
~/code/relay5
TLS handshake debugging
Root cause was a stale cert in the test fixture.
73·fix/tls·1mo
Load test scratchpad
10k concurrent sockets on the box — notes only.
9·main·1mo
~/code/parser3
Grammar experiments
Tried a PEG rewrite; slower, kept for reference.
27·exp/peg·2mo
Verdict on the take-back gesture: a persistent trailing icon, 44dp, one tap, no confirm. Swipe was rejected — this screen is entered rarely, so a gesture nobody rehearses is a gesture nobody finds; long-press was rejected because it hides the only verb this screen exists for behind the same gesture that got you here. A row that stays running keeps its green dot: archived ≠ stopped. Tap anywhere else opens the session and it stays archived.
Frame 4 · Feedback390×844 · row leaves · toast with the inverse verb
9:41
Archived13
~/code/cc-pocket5
Push notification spike
APNs relay worked end-to-end; parked until the daemon lands.
41·spike/apns·12d
Migrate settings store
Moved prefs off UserDefaults; merged in #418.
running·96·chore/prefs·3w
Onboarding copy pass
Rewrote the pairing screens; shipped in 1.4.
18·copy/onboard·3w
~/code/relay5
TLS handshake debugging
Root cause was a stale cert in the test fixture.
73·fix/tls·1mo
Back in ~/code/cc-pocketPush notification spike · still running
Archive
Verdict on feedback: a toast, but never an “Undo”. There is no undo stack, and there does not need to be — archive and unarchive are exact inverses, so the toast simply offers the opposite verb (here Archive; after archiving from the chat it reads Unarchive). It is honest about what happened, it names where the session went, and it costs engineering nothing. Same toast fires on the archive side, where it matters more: a row vanishing from a list you were reading needs a receipt. Toast is 4s, tap-to-dismiss, never blocks the composer.
Frame 5 · Empty390×844 · nothing archived yet
9:41
Archived

Nothing archived

Long-press any session and choose Archive to hide it here. It keeps running, and it stays hidden on every device until you bring it back.

The empty state teaches the gesture that fills it, and pre-empts the two questions the model raises: does it stop? (no) and is it just this phone? (no). No illustration, no button — there is nothing to act on here.
Desktop — one lightweight door, two different erasers The sidebar already has a hover . It is local, temporary, and forgetful. Archive is shared, persistent and deliberate. They must never look like siblings.
Frame 6 · Sidebar + right-click menu1180×680 · 260dp sidebar · ✕ and Archive side by side
cc-pocket
Active
Fix relay reconnect~/code/cc-pocket · now
Coverage report in CI~/code/cc-pocket · 2h
Token rotation spike~/code/cc-pocket · 5d
Parser
Port tokenizer to Rust~/code/parser · 1d
Bench harness~/code/parser · 3d
All projects…⌘P
Archived sessions14
Fix relay reconnect~/code/cc-pocket · fix/relay
CLAUDE
Backoff is in — the socket now reconnects within 400ms of the phone waking. Running the integration suite next.
edit · relay/src/socket.rsdone
Reply to Claude…
Rename…
Move to group
Copy path
Archive session⌘⌫
Remove from recents
Menu order = edit the session → file the session → hide the session, with a hairline before the last pair, and the two hiding verbs deliberately adjacent so the difference is read, not guessed. Archive session carries a box glyph and the shortcut; Remove from recents carries the same ✕ as the hover control, so the row control and the menu item are visibly one feature. Neither is red: nothing here loses work.
The row hover keeps its meaning by keeping its size — a 22px glyph that lives on the row, appears on hover, and undoes itself the moment you open the session again. Archive is never on the row: persistent, cross-device state is not a hover-weight action. And the footer entry carries a count, not a keycap — it reads as a place with contents, and it is the only sidebar row that grows when you archive something, which is the desktop's ambient receipt.
Frame 7 · ⌘K — ARCHIVED scope1180×680 · 560dp panel · rows 42dp · ⏎ open · ⌘⏎ unarchive
cc-pocket
Active
Fix relay reconnect~/code/cc-pocket · now
Coverage report in CI~/code/cc-pocket · 2h
All projects…⌘P
Archived sessions14
Fix relay reconnect~/code/cc-pocket · fix/relay
CLAUDE
Backoff is in — the socket now reconnects within 400ms of the phone waking.
Reply to Claude…
ARCHIVEDtls|14
~/code/relay
TLS handshake debugging~/code/relayUnarchive⌘⏎
Cert pinning notes~/code/relay
~/code/cc-pocket
TLS fixture refresh~/code/cc-pocket
Push notification spike~/code/cc-pocket
Open⌘⏎UnarchiveLeave archive
Ruling on the conflict: keep the ⌘K scope, do not build a second panel. A separate browser is a whole surface, a search field and an empty state for a list you visit monthly — and it would fork “find a session” into two places, which is exactly what archive is meant to un-fork. The palette already is the desktop's find-anything room; ARCHIVED is a scope inside it, entered by the sidebar row or by ⌘K → arch.
What actually fixes discoverability is not the hover icon — it is the footer legend, which is always visible and names both verbs the moment the scope opens. So: the icon shows on hover and permanently on the selected row (keyboard users never touch a mouse and must still see it), the label Unarchive is spelled out on the selected row only — icon alone on hover — and the footer carries ⏎ / ⌘⏎ / ⎋ at all times. Scope is a terracotta tag in the query field, so you always know which list you are typing into; ⎋ leaves the scope before it closes the panel.

Rulings on the three open questions

1 · mobile take-back: trailing icon / long-press / swipe?
Trailing icon. Persistent, 44dp, one tap, no confirm. The archive screen exists for exactly one verb — hiding it behind a gesture makes the room pointless. Swipe stays unimplemented rather than half-implemented.
2 · desktop second action: hover icon vs separate panel?
Keep the ⌘K scope. A separate panel duplicates search, empty state and navigation for a monthly-visit list. Discoverability is fixed by the always-on footer legend (⏎ / ⌘⏎) plus the icon pinned to the selected row, not by hover alone.
3 · ✕ vs Archive — how does each mean itself?
Different weight, different place, different words. ✕ is 22px, hover-only, on the row, worded Remove from recents — local, forgetful, self-healing. Archive is a menu verb with a box glyph and a shortcut, worded Archive session, captioned hides on all devices. They sit adjacent in the context menu so the pair is read once and never confused again.
4 · feedback for a vanishing (possibly running) row?
Toast, no undo stack. The toast offers the inverse verb, not an undo — same call, no engineering. It names the destination, and a running session's toast says still running, because a green dot disappearing is the one moment a user fears they killed something. Desktop shows no toast: the sidebar count bumping is receipt enough on a screen where the whole list is visible.
out of scope, on purpose
No delete, no expiry, no bulk select, no auto-archive suggestion, no change to the existing list or group layout. Archived sessions are excluded from the default ⌘K scope and from the sidebar — they only appear when you ask for them by name.